package org.api.result;

import lombok.Getter;
import org.springframework.http.HttpStatus;
import org.springframework.util.Assert;

import java.util.Optional;

@Getter
public enum RC implements IResultCode {
    OK(200, HttpStatus.OK),
    CREATED(201, HttpStatus.CREATED),
    ACCEPTED(202, HttpStatus.ACCEPTED),
    NO_CONTENT(204, HttpStatus.NO_CONTENT),
    BAD_REQUEST(400, HttpStatus.BAD_REQUEST),
    UNAUTHORIZED(401, HttpStatus.UNAUTHORIZED),
    PAYMENT_REQUIRED(402, HttpStatus.PAYMENT_REQUIRED),
    FORBIDDEN(403, HttpStatus.FORBIDDEN),
    NOT_FOUND(404, HttpStatus.NOT_FOUND),
    REQUEST_TIMEOUT(408, HttpStatus.REQUEST_TIMEOUT),
    PAYLOAD_TOO_LARGE(413, HttpStatus.PAYLOAD_TOO_LARGE),
    TOO_MANY_REQUESTS(429, HttpStatus.TOO_MANY_REQUESTS),
    //自定义
    PARAMETER_INVALID(460, HttpStatus.BAD_REQUEST),
    // /自定义
    INTERNAL_SERVER_ERROR(500, HttpStatus.INTERNAL_SERVER_ERROR),
    ;

    private final int code;

    private final HttpStatus httpStatus;

    private final String desc;

    RC(int code, HttpStatus httpStatus) {
        this(code, httpStatus, httpStatus.getReasonPhrase());
    }

    RC(int code, HttpStatus httpStatus, String desc) {
        this.code = code;
        this.httpStatus = httpStatus;
        this.desc = desc;
    }


    public static IResultCode of(int httpStatus) {
        return of(httpStatus, httpStatus, null);
    }

    public static IResultCode of(int httpStatus, int code) {
        return of(httpStatus, code, null);
    }

    public static IResultCode of(int httpStatus, int code, String desc) {
        HttpStatus status = Optional.of(httpStatus).map(HttpStatus::resolve).orElseGet(() -> {
            String valueOf = String.valueOf(code);
            if (valueOf.startsWith("2")) {
                return HttpStatus.OK;
            }
            if (valueOf.startsWith("4")) {
                return HttpStatus.BAD_REQUEST;
            }
            return HttpStatus.INTERNAL_SERVER_ERROR;
        });
        return of(status, code, desc);
    }

    public static IResultCode of(HttpStatus httpStatus) {
        return of(httpStatus, httpStatus.value(), null);
    }

    public static IResultCode of(HttpStatus httpStatus, int code) {
        return of(httpStatus, code, null);
    }

    public static IResultCode of(HttpStatus httpStatus, int code, String desc) {
        Assert.notNull(httpStatus, "httpStatus can not be null");
        return new CustomResultCode(httpStatus, code, desc);
    }

    static class CustomResultCode implements IResultCode {
        private final HttpStatus httpStatus;

        private final int code;

        private final String desc;

        CustomResultCode(HttpStatus httpStatus) {
            this(httpStatus, httpStatus.value(), httpStatus.getReasonPhrase());
        }

        CustomResultCode(HttpStatus httpStatus, int code, String desc) {
            this.httpStatus = httpStatus;
            this.code = code;
            this.desc = desc;
        }


        @Override
        public int getCode() {
            return code;
        }

        @Override
        public String getDesc() {
            return desc;
        }

        @Override
        public HttpStatus getHttpStatus() {
            return httpStatus;
        }
    }
}
